package com.study.principle;

/**
 * 6大设计原则：单一职责原则
 *
 * 一个类只负责一项职责/操作的原则，目的在于：
 *
 *  * 降低类的复杂度；
 *  * 提高类的可读性、系统的可维护性；
 *  * 降低变更引起的风险。
 *
 * 如果一个类负责多个职责，其中一项发生变化就要修改整个类，可能会导致其他职责运行错误，对于一个类只应该有一个引起它变化的原因。
 *
 * @Author 网易云课堂微专业-java高级开发工程师【allen老师】
 * @Version 1.0
 */
public class SingleResponsibilityPrinciple {
    public static void main(String[] args) {
        // 1
//        Animal animal = new Animal();
//        animal.breathe("牛");
//        animal.breathe("羊");
//        animal.breathe("猪");

        // 2
//        System.out.println("*************************");
//        Terrestrial terrestrial = new Terrestrial();
//        terrestrial.breathe("牛");
//        terrestrial.breathe("羊");
//        terrestrial.breathe("猪");
//
//        Aquatic aquatic = new Aquatic();
//        aquatic.breathe("鱼");

        // 3
        System.out.println("*************************");
        Animal animal2 = new Animal();
        animal2.breathe("牛");
        animal2.breathe("羊");
        animal2.breathe("猪");
        animal2.breathe("鱼");

        // 4
        System.out.println("*************************");
        Animal animal3 = new Animal();
        animal3.breathe("牛");
        animal3.breathe("羊");
        animal3.breathe("猪");
        animal3.breathe2("鱼");
    }
}

/**
 * 1、用一个类描述动物呼吸这个场景
 */
//class Animal {
//    public void breathe(String animal) {
//        System.out.println(animal + "呼吸空气");
//    }
//}

/**
 * 2、程序上线后，发现问题了，并不是所有的动物都呼吸空气的，比如鱼就是呼吸水的。
 *    修改时如果遵循单一职责原则，需要将Animal类细分为陆生动物类Terrestrial，水生动物Aquatic
 */
//class Terrestrial {
//    public void breathe(String animal) {
//        System.out.println(animal + "呼吸空气");
//    }
//}
//
//class Aquatic {
//    public void breathe(String animal) {
//        System.out.println(animal + "呼吸水");
//    }
//}

/**
 * 3、我们会发现如果这样修改花销是很大的，除了将原来的类分解之外，还需要修改客户端。
 *    而直接修改类Animal来达成目的虽然违背了单一职责原则，但花销却小的多
 */
//class Animal {
//    public void breathe(String animal) {
//        if ("鱼".equals(animal)) {
//            System.out.println(animal + "呼吸水");
//        } else {
//            System.out.println(animal + "呼吸空气");
//        }
//    }
//}


/**
 * 4、我们会发现如果这样修改花销是很大的，除了将原来的类分解之外，还需要修改客户端。
 *    而直接修改类Animal来达成目的虽然违背了单一职责原则，但花销却小的多
 */
class Animal {
    public void breathe(String animal) {
        System.out.println(animal + "呼吸空气");
    }

    public void breathe2(String animal) {
        System.out.println(animal + "呼吸水");
    }
}

/*
可以看到，这种修改方式没有改动原来的方法，而是在类中新加了一个方法，
这样虽然也违背了单一职责原则，但在方法级别上却是符合单一职责原则的，
因为它并没有动原来方法的代码。这三种方式各有优缺点，那么在实际编程中，采用哪一中呢？
其实这真的比较难说，需要根据实际情况来确定。

我的原则是：只有逻辑足够简单，才可以在代码级别上违反单一职责原则；
          只有类中方法数量足够少，才可以在方法级别上违反单一职责原则；
 */